#!/usr/bin/env python
# -*- coding: utf-8 -*-

import requests
import json
import time
import sys
import random
import base64
import os
import aes
from urllib.parse import urljoin
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad, unpad

# 添加UI
from rich.console import Console
from rich.panel import Panel
from rich.progress import Progress, SpinnerColumn, TextColumn, BarColumn, TimeElapsedColumn
from rich.table import Table
from rich.prompt import Prompt, Confirm
HAS_RICH = True

console = Console() if HAS_RICH else None

class AutoStudy:
    def __init__(self):
        self.base_url = "https://xuexi.qsxueli.com"
        self.session = requests.Session()
        self.token = None
        self.headers = {
            "Content-Type": "application/x-www-form-urlencoded",
            "Qs-Client-Type": "PC"
        }
        self.aes = aes.AESCipher()

    def print_info(self, message, style="info"):
        """打印信息，支持rich格式化"""
        if HAS_RICH:
            styles = {
                "info": "blue",
                "success": "green",
                "warning": "yellow",
                "error": "red bold",
                "title": "cyan bold"
            }
            console.print(f"[{styles.get(style, 'white')}]{message}[/{styles.get(style, 'white')}]")
        else:
            print(message)

    def print_title(self, title):
        """打印标题"""
        if HAS_RICH:
            console.print(Panel(f"[bold cyan]{title}[/bold cyan]", border_style="cyan"))
        else:
            print("=" * 50)
            print(title)
            print("=" * 50)

    def login(self, mobile, password, captcha="-"):
        """登录获取token"""
        url = urljoin(self.base_url, "/api/v2/login/password")

        # 使用AES加密密码
        encrypted_password = self.aes.encrypt(password)
        # self.print_info(f"加密后的密码: {encrypted_password}", "info")

        data = {
            "mobile": mobile,
            "password": encrypted_password,
            "captcha": captcha
        }

        try:
            if HAS_RICH:
                with console.status("[bold blue]正在登录...[/bold blue]"):
                    response = self.session.post(url, data=data, headers=self.headers)
                    result = response.json()
            else:
                self.print_info("正在登录...")
                response = self.session.post(url, data=data, headers=self.headers)
                result = response.json()

            if result.get("code") == 0:
                self.token = result["data"]["token"]
                self.headers["Authorization"] = f"Bearer {self.token}"
                # if 'meedudemo_session' in self.session.cookies:
                #     self.print_info(f"获取到cookie: meedudemo_session={self.session.cookies['meedudemo_session']}", "info")
                self.print_info("登录成功！", "success")
                return True
            else:
                self.print_info(f"登录失败: {result.get('message', '未知错误')}", "error")
                return False
        except Exception as e:
            self.print_info(f"登录异常: {str(e)}", "error")
            return False

    def get_courses(self):
        """获取所有课程"""
        url = urljoin(self.base_url, "/api/v2/member/courses")
        params = {
            "term": "1",
            "pagsize": "999"
        }

        try:
            if HAS_RICH:
                with console.status("[bold blue]正在获取课程列表...[/bold blue]"):
                    response = self.session.get(url, params=params, headers=self.headers)
                    result = response.json()
            else:
                self.print_info("正在获取课程列表...")
                response = self.session.get(url, params=params, headers=self.headers)
                result = response.json()

            if result.get("code") == 0:
                self.print_info(f"成功获取到 {len(result['data']['data'])} 门课程", "success")
                return result["data"]["data"]
            else:
                self.print_info(f"获取课程失败: {result.get('message', '未知错误')}", "error")
                return []
        except Exception as e:
            self.print_info(f"获取课程异常: {str(e)}", "error")
            return []

    def get_course_detail(self, course_id):
        """获取课程详情"""
        url = urljoin(self.base_url, f"/api/v2/course/{course_id}")

        try:
            if HAS_RICH:
                with console.status(f"[bold blue]正在获取课程详情 (ID: {course_id})...[/bold blue]"):
                    response = self.session.get(url, headers=self.headers)
                    result = response.json()
            else:
                self.print_info(f"正在获取课程详情 (ID: {course_id})...")
                response = self.session.get(url, headers=self.headers)
                result = response.json()

            if result.get("code") == 0:
                # self.print_info(f"Videos数据类型: {type(result['data']['videos'])}")
                return result["data"]
            else:
                self.print_info(f"获取课程详情失败: {result.get('message', '未知错误')}", "error")
                return None
        except Exception as e:
            self.print_info(f"获取课程详情异常: {str(e)}", "error")
            return None

    def submit_video_record(self, video_id, course_id, duration, study_time):
        """提交视频学习记录"""
        url = urljoin(self.base_url, f"/api/v2/video/{video_id}/record")
        data = {
            "duration": duration,
            "study_time": study_time,
            "course_id": course_id
        }

        try:
            if HAS_RICH:
                with console.status(f"[bold blue]正在提交学习记录 (视频ID: {video_id})...[/bold blue]"):
                    response = self.session.post(url, data=data, headers=self.headers)
                    result = response.json()
            else:
                self.print_info(f"正在提交学习记录 (视频ID: {video_id})...")
                response = self.session.post(url, data=data, headers=self.headers)
                result = response.json()

            if result.get("code") == 0:
                return True
            else:
                self.print_info(f"提交学习记录失败: {result.get('message', '未知错误')}", "error")
                return False
        except Exception as e:
            self.print_info(f"提交学习记录异常: {str(e)}", "error")
            return False

    def auto_study_course(self, course_id):
        """自动学习课程"""
        # 获取课程详情
        course_detail = self.get_course_detail(course_id)
        if not course_detail:
            return False

        course_title = course_detail["course"]["title"]
        self.print_title(f"开始学习课程: {course_title}")

        # 获取所有视频
        videos_data = course_detail["videos"]
        total_videos = 0
        completed_videos = 0
        all_videos = []

        # 处理不同的数据结构
        if isinstance(videos_data, dict):
            # 计算总视频数并收集所有视频
            for chapter_id, videos in videos_data.items():
                total_videos += len(videos)
                for video in videos:
                    all_videos.append((chapter_id, video))
        # 如果videos_data是列表（直接的视频列表）
        elif isinstance(videos_data, list):
            total_videos = len(videos_data)
            for video in videos_data:
                all_videos.append((None, video))
        else:
            self.print_info(f"未知的视频数据结构: {type(videos_data)}", "error")
            return False

        # 创建进度条
        if HAS_RICH and total_videos > 0:
            with Progress(
                SpinnerColumn(),
                TextColumn("[bold blue]{task.description}"),
                BarColumn(),
                TextColumn("[bold]{task.completed}/{task.total}"),
                TimeElapsedColumn(),
            ) as progress:
                task = progress.add_task(f"[cyan]学习进度", total=total_videos)

                # 遍历所有视频
                for chapter_id, video in all_videos:
                    video_id = video["id"]
                    video_title = video["title"]
                    need_study_time = video.get("need_study_time", 0)
                    duration = video["duration"]

                    # 更新任务描述
                    progress.update(task, description=f"[cyan]正在学习: {video_title}")

                    # 检查是否已完成
                    is_finished = False
                    if video.get("student_learn_progress"):
                        for progress_item in video["student_learn_progress"]:
                            if progress_item.get("is_finish") == 1:
                                is_finished = True
                                break

                    if is_finished:
                        # progress.console.print(f"[yellow]视频 [{video_title}] 已完成学习，跳过[/yellow]")
                        completed_videos += 1
                        progress.update(task, advance=1)
                        continue

                    # 提交学习记录
                    study_time = need_study_time if need_study_time else duration
                    result = self.submit_video_record(video_id, course_id, duration, study_time)

                    if result:
                        # 只在成功时显示简短信息
                        progress.console.print(f"[green]✓ {video_title}[/green]")
                        completed_videos += 1
                    else:
                        progress.console.print(f"[red]✗ {video_title}[/red]")

                    # 随机等待1-3秒，避免请求过快
                    wait_time = random.uniform(1, 3)
                    time.sleep(wait_time)

                    # 更新进度
                    progress.update(task, advance=1)
        else:
            # 遍历所有视频
            for chapter_id, video in all_videos:
                video_id = video["id"]
                video_title = video["title"]
                need_study_time = video.get("need_study_time", 0)
                duration = video["duration"]

                # 检查是否已完成
                is_finished = False
                if video.get("student_learn_progress"):
                    for progress in video["student_learn_progress"]:
                        if progress.get("is_finish") == 1:
                            is_finished = True
                            break

                if is_finished:
                    # self.print_info(f"视频 [{video_title}] 已完成学习，跳过", "warning")
                    completed_videos += 1
                    continue

                self.print_info(f"学习: {video_title}")

                # 提交学习记录
                study_time = need_study_time if need_study_time else duration
                result = self.submit_video_record(video_id, course_id, duration, study_time)

                if result:
                    # 简化成功信息
                    self.print_info(f"✓ {video_title}", "success")
                    completed_videos += 1
                else:
                    self.print_info(f"✗ {video_title}", "error")

                # 随机等待1-3秒，避免请求过快
                wait_time = random.uniform(1, 3)
                time.sleep(wait_time)

        self.print_info(f"课程 [{course_title}] 学习完成，总共 {total_videos} 个视频，成功提交 {completed_videos} 个", "success")
        return True

def main():
    auto_study = AutoStudy()

    if HAS_RICH:
        console.print(Panel.fit(
            "[bold cyan]在线轻松学 - 自动刷课脚本[/bold cyan]\n"
            "[yellow]注意: 开源项目: https://gitee.com/xxxhhy/easy-learning-classroom[/yellow]\n"
            "[blue]邮箱: hhy5562877@163.com[/blue]"
            "[red]禁止: 禁止倒卖本脚本, 如有发现请邮箱联系",
            border_style="cyan"
        ))
    else:
        auto_study.print_title("在线轻松学 - 自动刷课脚本")
        auto_study.print_info("注意: 密码将使用AES加密后提交", "warning")

    # 登录
    if HAS_RICH:
        mobile = Prompt.ask("[bold blue]请输入账号[/bold blue]")
        # 使密码可见
        password = Prompt.ask("[bold blue]请输入密码[/bold blue]")
        captcha = "-"  # 默认验证码为"-"
    else:
        mobile = input("请输入账号: ")
        password = input("请输入密码: ")
        captcha = "-"  # 默认验证码为"-"

    if not auto_study.login(mobile, password, captcha):
        auto_study.print_info("登录失败，程序退出", "error")
        sys.exit(1)

    # 获取课程列表
    courses = auto_study.get_courses()

    if not courses:
        auto_study.print_info("未获取到课程，程序退出", "error")
        sys.exit(1)

    # 显示课程列表
    if HAS_RICH:
        table = Table(title="课程列表")
        table.add_column("序号", style="cyan", justify="right")
        table.add_column("课程名称", style="green")
        table.add_column("课程ID", style="yellow")
        table.add_column("视频数量", style="magenta")
        table.add_column("已完成", style="blue")

        for i, course in enumerate(courses):
            course_info = course["course"]
            video_finish = course.get("video_finish_number", 0)
            video_total = course.get("course_chapter_count", 0)
            table.add_row(
                str(i+1),
                course_info["title"],
                str(course_info["id"]),
                str(video_total),
                f"{video_finish}/{video_total}"
            )

        console.print(table)

        # 选择课程
        console.print("[bold blue]请选择要刷取的课程编号 (输入0刷取所有课程)[/bold blue]")
        choice_str = Prompt.ask(
            "[bold blue]请输入[/bold blue]",
            default="0",
            show_default=True
        )

        try:
            choice = int(choice_str)
            if choice == 0:
                # 刷取所有课程
                if Confirm.ask("[bold yellow]确定要刷取所有课程吗?[/bold yellow]"):
                    for course in courses:
                        auto_study.auto_study_course(course["course"]["id"])
            elif 1 <= choice <= len(courses):
                # 刷取选定课程
                selected_course = courses[choice-1]
                auto_study.auto_study_course(selected_course["course"]["id"])
            else:
                console.print("[bold red]无效的选择，程序退出[/bold red]")
                sys.exit(1)
        except ValueError:
            console.print("[bold red]请输入有效的数字，程序退出[/bold red]")
            sys.exit(1)
    else:
        auto_study.print_info("\n课程列表:", "title")
        for i, course in enumerate(courses):
            course_info = course["course"]
            video_finish = course.get("video_finish_number", 0)
            video_total = course.get("course_chapter_count", 0)
            auto_study.print_info(f"{i+1}. {course_info['title']} (ID: {course_info['id']}, 进度: {video_finish}/{video_total})")

        # 选择课程
        while True:
            try:
                choice = int(input("\n请选择要刷取的课程编号(输入0刷取所有课程): "))
                if choice == 0:
                    # 刷取所有课程
                    confirm = input("确定要刷取所有课程吗? (y/n): ")
                    if confirm.lower() == 'y':
                        for course in courses:
                            auto_study.auto_study_course(course["course"]["id"])
                    break
                elif 1 <= choice <= len(courses):
                    # 刷取选定课程
                    selected_course = courses[choice-1]
                    auto_study.auto_study_course(selected_course["course"]["id"])
                    break
                else:
                    auto_study.print_info("无效的选择，请重新输入", "error")
            except ValueError:
                auto_study.print_info("请输入有效的数字", "error")

    auto_study.print_info("\n程序执行完毕！", "success")

if __name__ == "__main__":
    main()
